package com.ionehe.group.common.file.ex.service.impl;

import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.ionehe.group.common.file.ex.repository.dao.UserFolderDao;
import com.ionehe.group.common.file.ex.repository.dataobject.UserFolder;
import com.ionehe.group.common.file.ex.service.UserFolderService;
import com.ionehe.group.common.io.Response;
import com.ionehe.group.common.uaa.ex.enums.ErrorMessages;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Copyright © 2020 moma有限公司
 * Date: 2020/9/23
 * Time: 上午9:40
 *
 * @author 2020年 <a href="mailto:chenwd@moma.ai">秀</a>
 * <p>
 * 操作user_folder
 */
@Service
@Slf4j
public class UserFolderServiceImpl implements UserFolderService {
    @Resource
    private UserFolderDao userFolderDao;

    @Override
    public Response<Long> createFolder(UserFolder folder) {
        try {
            Preconditions.checkArgument(folder.getFolder().length() <= 128, ErrorMessages.USER_FOLDER_TOO_LONG.toString());
            folder.setFolder(newFolderName(folder.getPid(), folder.getFolder(), 0));
            UserFolder uf = new UserFolder();
            uf.setCreateBy(folder.getCreateBy());
            uf.setPid(folder.getPid());
            uf.setLevel(folder.getLevel());
            uf.setFolder(folder.getFolder());
            UserFolder f = userFolderDao.selectOne(uf);

            if (Objects.nonNull(f)) {
                return Response.yes(f.getId());
            }

            //文件夹层级
            int level = 1;

            if (folder.getPid() != 0L) {
                UserFolder uff = new UserFolder();

                uff.setPid(folder.getPid());

                UserFolder parentFolder = userFolderDao.selectOne(uf);

                checkNotNull(parentFolder, ErrorMessages.FOLDER_PARENT_FOUND_FAIL.toString());

                level = parentFolder.getLevel() + 1;
            }

            folder.setLevel(level);

            userFolderDao.insertSelective(folder);

            log.info("Item[]UserFolderService[]createFolder[]success, folder={}", folder);

            return Response.yes(folder.getId());
        } catch (NullPointerException e) {
            log.error("Item[]UserFolderService[]createFolder[]error, folder={}, cause={}",
                    folder, e.getMessage());
            return Response.no(e.getMessage());
        } catch (Exception e) {
            log.error("Item[]UserFolderService[]createFolder[]error, folder={}, cause={}",
                    folder, Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.FOLDER_CREATE_FAIL.toString());
        }
    }

    @Override
    public Response<Boolean> updateFolder(UserFolder folder) {
        try {
            UserFolder uf = new UserFolder();
            uf.setId(folder.getId());
            UserFolder userFolder = userFolderDao.selectOne(uf);

            if (!Objects.equals(userFolder.getFolder(), folder.getFolder())) {
                folder.setFolder(this.newFolderName(folder.getPid(), folder.getFolder(), 0));
            }
            Boolean isSuccess = userFolderDao.updateByPrimaryKeySelective(folder) < 0 ? Boolean.FALSE : Boolean.TRUE;
            log.info("UserFolderService[]updateFolder[]success, folder={}", folder);
            return Response.yes(isSuccess);
        } catch (NullPointerException e) {
            log.error("UserFolderService[]updateFolder[]error, folder={}, cause={}",
                    folder, e.getMessage());
            return Response.no(e.getMessage());
        } catch (Exception e) {
            log.error("UserFolderService[]updateFolder[]error, folder={}, cause={}",
                    folder, Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.FOLDER_UPDATE_FAIL.toString());
        }
    }

    @Override
    public Response<Boolean> moveFolder(Long folderId, Long newPid) {
        try {
            UserFolder uf = new UserFolder();
            uf.setId(folderId);
            UserFolder folder = userFolderDao.selectOne(uf);
            uf.setId(newPid);
            UserFolder parent = userFolderDao.selectOne(uf);
            //设置pid为新的pid
            folder.setPid(newPid);
            folder.setLevel(parent.getLevel() + 1);
            Boolean isSuccess = userFolderDao.updateByPrimaryKeySelective(folder) < 0 ? Boolean.FALSE : Boolean.TRUE;
            log.info("UserFolderService[]updateFolder[]success, folderId={}, newPid={}", folderId, newPid);
            return Response.yes(isSuccess);
        } catch (NullPointerException e) {
            log.error("UserFolderService[]updateFolder[]error, folderId={}, newPid={}, cause={}",
                    folderId, newPid, e.getMessage());
            return Response.no(e.getMessage());
        } catch (IllegalArgumentException e) {
            log.error("UserFolderService[]updateFolder[]error, folderId={}, newPid={}, cause={}",
                    folderId, newPid, e.getMessage());
            return Response.no(e.getMessage());
        } catch (Exception e) {
            log.error("UserFolderService[]updateFolder[]error, folderId={}, newPid={}, cause={}",
                    folderId, newPid, Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.FOLDER_MOVE_FAIL.toString());
        }
    }

    @Override
    public Response<Boolean> deleteFolder(Long folderId) {
        try {
            UserFolder uf = new UserFolder();

            uf.setId(folderId);

            userFolderDao.deleteByPrimaryKey(folderId);

            log.info("UserFolderService[]deleteFolder[]success, folderId={}", folderId);

            return Response.yes(Boolean.TRUE);
        } catch (NullPointerException e) {
            log.error("UserFolderService[]updateFolder[]error, folderId={}, cause={}",
                    folderId, e.getMessage());
            return Response.no(e.getMessage());
        } catch (Exception e) {
            log.error("UserFolderService[]updateFolder[]error, folderId={}, cause={}",
                    folderId, Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.FOLDER_DELETE_FAIL.toString());
        }
    }

    @Override
    public Response<UserFolder> findById(Long folderId) {
        try {
            UserFolder uf = new UserFolder();

            uf.setId(folderId);

            UserFolder userFolder = userFolderDao.selectByPrimaryKey(folderId);

            return Response.yes(userFolder);
        } catch (Exception e) {
            log.error("UserFolderService[]findById[]error, folderId={}, cause={}",
                    folderId, Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.FOLDER_NOT_FOUND.toString());
        }
    }

    @Override
    public Response<List<UserFolder>> findByCreatBy(Long userId) {
        UserFolder uf = new UserFolder();
        uf.setCreateBy(userId);
        return Response.yes(userFolderDao.select(uf));
    }


    /**********************************              service函数分界线             **************************************/

    private void realPath(List<UserFolder> folders, Long folderId) {
        UserFolder uf = new UserFolder();
        uf.setId(folderId);
        UserFolder userFolder = userFolderDao.selectOne(uf);
        if (userFolder != null) {
            folders.add(userFolder);
            this.realPath(folders, userFolder.getPid());
        }

    }

    private String newFolderName(Long pid, String folder, Integer index) {
        String newFolder = index == 0 ? folder : folder + "(" + index + ")";
        UserFolder uf = new UserFolder();
        uf.setPid(pid);
        uf.setFolder(newFolder);
        List<UserFolder> folders = userFolderDao.select(uf);
        return folders.isEmpty() ? newFolder : this.newFolderName(pid, folder, index + 1);
    }
}
